/*
SandBox2D - Tools and Middleware 2011/2012 Assignment 1  - Sam Latif MA002HA

A heavily modified testbed, with added runtime shape creation/editing, FMOD sounds and XML meta data save/load functionality

Box.h - Contains our Box shape class and method declarations
*/

#ifndef BOX_H_
#define BOX_H_

class Box
{
private:

	b2Body* box_;

	int bodyType_;
	int fixedRotation_;
	b2Vec2 size_;
	b2Vec2 position_;
	float angle_;
	float mass_;
	float restitution_;
	float friction_;
	float velocityX_;
	float velocityY_;
	float angularVelocity_;
   
public:
	// constructor
	Box(): bodyType_(0), fixedRotation_(0),  size_(0,0), position_(0,0), angle_(0.0f), mass_(0.0f), restitution_(0.0f), friction_(0.0), velocityX_(0.0f), velocityY_(0.0f), angularVelocity_(0.0f) {}
	
	// return shape attribute methods
	b2Body* getBody() {return box_;}

	int getBodyType() {return bodyType_;}

	int getFixRotation() {return fixedRotation_;}

	b2Vec2 getSize() {return size_;}

	b2Vec2 getPosition() {return position_;}

	float getAngle() {return angle_;}

	float getMass() {return mass_;}

	float getRestitution() {return restitution_;}

	float getFriction()	{return friction_;}

	float getVelocityX() {return velocityX_;}

	float getVelocityY() {return velocityY_;}

	float getAngularVelocity() {return angularVelocity_;}

	static const char *typeName()	{return "Box";}
	
	// set new box attributes
	void newUserGeneratedBox(int bodyType, int fixedRotation, b2Vec2 size, b2Vec2 position, float angle, float density, float restitution, float friction, b2Vec2 linearVelocity, float angularVelocity)
	{
		bodyType_ = bodyType;
		fixedRotation_ = fixedRotation;
		size_ = size;
		position_ = position;
		angle_ = angle;
		mass_ = density;
		restitution_ = restitution;
		friction_ = friction;
		velocityX_ = linearVelocity.x;
		velocityY_ = linearVelocity.y;
		angularVelocity_ = angularVelocity;
	}

	// metadata: the contents of our class
	void meta(GsgMeta &meta)
	{
		meta.attr("getBodyType", bodyType_);
		meta.attr("getFixRotation", fixedRotation_);
		meta.attr("Width", size_.x);
		meta.attr("Height", size_.y);
		meta.attr("X", position_.x);
		meta.attr("Y", position_.y);
		meta.attr("getAngle", angle_);
		meta.attr("getMass", mass_);
		meta.attr("getRestitution", restitution_);
		meta.attr("getFriction", friction_);
		meta.attr("getVelocityX", velocityX_);
		meta.attr("getVelocityY", velocityY_);
		meta.attr("getAngularVelocity", angularVelocity_);
	}

	// load shape to world
 	void addToWorld(b2World* world)
	{
		b2PolygonShape shape;
		shape.SetAsBox(size_.x, size_.y);

		b2BodyDef body;

		switch(bodyType_)
		{
		case 0:
			{
				body.type = b2_staticBody;
			}
			break;
		case 1:
			{
				body.type = b2_dynamicBody;
			}
			break;
		case 2:
			{
				body.type = b2_kinematicBody;
			}
			break;
		}

		body.position.Set(position_.x, position_.y);
		body.angle = angle_;
		body.fixedRotation = fixedRotation_ > 0 ? 1 : 0;
		body.linearVelocity = b2Vec2(velocityX_, velocityY_);
		body.angularVelocity = angularVelocity_;
		box_ = world->CreateBody(&body);
		
		b2FixtureDef fixDef;
		fixDef.shape = &shape;
		fixDef.density = mass_;
		fixDef.friction = friction_;

		box_->CreateFixture(&fixDef);
	}

	//grab and save current position and velocities of shape
	void saveShape()	
	{
		position_.Set(box_->GetPosition().x, box_->GetPosition().y);
		angle_	= box_->GetAngle();
		velocityX_ = box_->GetLinearVelocity().x;
		velocityY_ = box_->GetLinearVelocity().y;
		angularVelocity_ = box_->GetAngularVelocity();
	}

};

#endif